﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;

namespace FezPosterClient
{
    class Changer
    {
        private string session_id;

        private StatusStrip strip = null;

        private Label starLabel = null;

        public bool isStop{private get; set;}

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="session_id"></param>
        /// <param name="strip"></param>
        public Changer(string session_id, StatusStrip strip = null, Label starLabel = null)
        {
            this.session_id = session_id;
            this.strip = strip;
            this.starLabel = starLabel;
            this.isStop = false;
        }

        /// <summary>
        /// ステータスバーにメッセージ表示
        /// </summary>
        /// <param name="msg"></param>
        private void setStripMessage(string msg)
        {
            if (this.strip == null) return;
            foreach (ToolStripItem item in strip.Items)
            {
                if (item.Name == "stripLabel")
                {
                    item.Text = msg;
                    Application.DoEvents();
                    return;
                }
            }
        }

        /// <summary>
        /// スター所持数からアイテム価格を原産
        /// </summary>
        /// <param name="itemPrice"></param>
        private void updateStarLabel(string item_cd)
        {
            if (this.starLabel == null) return;
            int current = Int32.Parse(starLabel.Text);
            current = current - Int32.Parse(Constant.ItemPrice[item_cd]);
            this.starLabel.Text = current.ToString();
        }

        /// <summary>
        /// 現在の進捗状態を表示
        /// </summary>
        /// <param name="nowCount"></param>
        /// <param name="allCount"></param>
        /// <param name="item_cd"></param>
        private void showStripCurrent(int nowCount, int allCount, string item_cd)
        {
            string msg = "【" + Constant.ItemNames[item_cd] + "】交換中 ... " + nowCount.ToString() + "/" + allCount.ToString();
            setStripMessage(msg);
        }

        /// <summary>
        /// 交換処理を実行
        /// </summary>
        /// <param name="charactor_cd"></param>
        /// <param name="item_cd"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public bool run(string charactor_cd, string item_cd, int count)
        {
            string itemSelectUrl = Constant.itemSelectUrl + item_cd;
            string itemConfirmUrl = Constant.itemConfirmUrl + Constant.ItemPrice[item_cd];
            string itemConfirmReferer = Constant.itemConfirmRefererUrl + Constant.ItemPrice[item_cd];

            string postData = Constant.postCharactorName + "=" + charactor_cd.Replace(",", "%2C") + "&x=113&y=26";

            for (int current = 1; current <= count; current++)
            {
                showStripCurrent(current, count, item_cd);

                if (isStop)
                {
                    chancel(current, count, item_cd);
                    return false;
                }

                // アイテムリストに遷移（多分ここで何かしてるから）
                WebClientEx client = Util.getWebClient(this.session_id);
                string res = client.DownloadString(Constant.itemListUrl);
                Util.wait();

                if (isStop)
                {
                    chancel(current, count, item_cd);
                    return false;
                }
                
                // アイテム選択後の画面へ
                // ポイントが足りない場合ここで失敗する
                client.Headers["Referer"] = Constant.itemListUrl;
                res = client.DownloadString(itemSelectUrl);
                if (!isSuccessSelectItem(res, item_cd))
                {
                    setStripMessage("【" + Constant.ItemNames[item_cd] + 
                        "】アイテムの選択に失敗しました。ポイントが足りない可能性があります。 ... " + 
                        current.ToString() + "/" + count.ToString()
                    );
                    return false;
                }
                Util.wait();
                if (isStop)
                {
                    chancel(current, count, item_cd);
                    return false;
                }

                // 確認画面　キャラクターコードと一緒にPOST
                client.Headers["Referer"] = itemSelectUrl;
                client.Headers["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)";
                client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
                res = client.UploadString(itemConfirmUrl, "POST", postData);
                Util.wait();
                if (isStop)
                {
                    chancel(current, count, item_cd);
                    return false;
                }

                // 完了画面　GET
                client.Headers["Referer"] = itemConfirmReferer;
                client.Headers["Content-Type"] = "";
                res = client.DownloadString(Constant.itemBuyUrl);
                if (!isSuccessBuy(res))
                {
                    setStripMessage("【" + Constant.ItemNames[item_cd] +
                        "】アイテムの購入に失敗しました。 ... " +
                        current.ToString() + "/" + count.ToString()
                    );
                    return false;
                }
                Util.wait();
                updateStarLabel(item_cd);
            }

            setStripMessage("【" + Constant.ItemNames[item_cd] +
                "】交換終了 ... " +
                count.ToString() + "/" + count.ToString()
            );
            return true;
        }

        private void chancel(int nowCount, int allCount, string item_cd)
        {
            string msg = "【" + Constant.ItemNames[item_cd] + "】交換のキャンセル　交換済み ... " + (nowCount - 1).ToString() + "/" + allCount.ToString();
            setStripMessage(msg);
        }

        /// <summary>
        /// アイテムの選択に成功したか返す
        /// </summary>
        /// <param name="res"></param>
        /// <param name="item_cd"></param>
        /// <returns></returns>
        private bool isSuccessSelectItem(string res, string item_cd)
        {
            string name = Constant.ItemNames[item_cd];
            Regex regx = new Regex(name, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            return (regx.Match(res)).Success;
        }

        private bool isSuccessBuy(string res)
        {
            Regex regx = new Regex("交換手続きが完了しました。", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            return (regx.Match(res)).Success;
        }
    }
}
